﻿#ifndef __SBHS_H__
#define __SBHS_H__

#if _MSC_VER
#pragma once
#endif

#include "sbcs.h"

K_EXTERN_C_BEGIN

//////////////////////////////////////////////////////////////////////////
// internal operation
KAPI void k_typelib(void);
KAPI void k_h_lock(void);
KAPI void k_h_unlock(void);


//////////////////////////////////////////////////////////////////////////
// declaration

// type
typedef kuintptr kType;

// structure
typedef struct kTypeInfo kTypeInfo;
typedef struct kVar kVar;
typedef struct kScv kScv;
typedef struct kBase kBase;
typedef struct kDescBase kDescBase;
typedef struct kNodeBase kNodeBase;
typedef struct kRedStr kRedStr;
typedef struct kRedWcs kRedWcs;
typedef struct kRedTbl kRedTbl;
typedef struct kRedFn kRedFn;
typedef struct kHsm kHsm;
typedef struct kRnh kRnh;

typedef struct khParamDesc khParamDesc;
typedef struct khParamShed khParamShed;

// callback
typedef kvoid(*kTypeFunc)(kType);

typedef kBase* (*khCnstFunc)(kpointer);
typedef kpointer (*khDispFunc)(kBase*);

typedef kbool (*khEqFunc)(kNodeBase*, kconstpointer);
typedef ksize_t (*khHashFunc)(kconstpointer);
typedef kconstpointer (*khKeyFunc)(kNodeBase*);

typedef kint(*khOpFunc)(kVar*);
typedef kint(*khOpNewFunc)(kVar*, kint, kVar*);
typedef const kchar* (*khOpTosFunc)(const kVar*, char*, kint, kint*);

typedef kvoid(*khParamPropFunc)(kpointer, ksize_t, kVar*);
typedef kint(*khParamCallFunc)(kScv*);

// type range
#define K_MAX_TYPE_LIMIT					1024
#define K_POS_TYPE_CUSTOM					64

// type flags
#define KTIF_RED							0x0001
#define KTIF_VALUE							0x0010
#define KTIF_SEALED							0x4000
#define KTIF_ABSTRACT						0x8000

// internal types
#define KTYPE_NULL							((kType)0)
#define KTYPE_PARAM							((kType)1)
#define KTYPE_POINTER						((kType)2)
#define KTYPE_SYMBOL						((kType)3)
#define KTYPE_BOOL							((kType)4)
#define KTYPE_INT							((kType)5)
#define KTYPE_LONG							((kType)6)
#define KTYPE_FLOAT							((kType)7)
#define KTYPE_DOUBLE						((kType)8)

#define KTYPE_BASE							((kType)10)
#define KTYPE_DESC							((kType)11)
#define KTYPE_NODE							((kType)12)

#define KTYPE_FN							((kType)14)
#define KTYPE_STR							((kType)15)
#define KTYPE_WCS							((kType)16)
#define KTYPE_TBL							((kType)17)
#define KTYPE_ARR							((kType)18)

#define KTYPE_HSM							((kType)19)
#define KTYPE_RNH							((kType)20)

// type operators
enum khOps
{
	KHOP_NOP,

	KHOP_POS,		//  +   
	KHOP_NEG,		//  - 
	KHOP_SIG,		//  ! 
	KHOP_NOT,		//  ~ 
	KHOP_INC,		//  ++
	KHOP_DEC,		//  --

	KHOP_MUL,		//  * 
	KHOP_DIV,		//  / 
	KHOP_MOD,		//  % 
	KHOP_ADD,		//  + 
	KHOP_SUB,		//  - 
	KHOP_SHL,		//  <<
	KHOP_SHR,		//  >>
	KHOP_BLT,		//  < 
	KHOP_BLE,		//  <=
	KHOP_BEQ,		//  ==
	KHOP_BNE,		//  !=
	KHOP_AND,		//  & 
	KHOP_XOR,		//  ^ 
	KHOP_OR,		//  | 

	KHOP_STV,		// store
	KHOP_LDV,		// load

	KHOP_NEW,		// new
	KHOP_TOS,		// to string

	KHOP_MNM,		// !!! not op !!!

	KHOP_MAX_VALUE
};

// param types
enum khParamTypes
{
	KHPRM_VAR,
	KHPRM_PROP,
	KHPRM_FUNC,
	KHPRM_RFN,
};

// param property types
enum khParamPropTypes
{
	KHPRMPROP_BOOL,
	KHPRMPROP_POINTER,
	KHPRMPROP_SBYTE,
	KHPRMPROP_SHORT,
	KHPRMPROP_INT,
	KHPRMPROP_LONG,
	KHPRMPROP_BYTE,
	KHPRMPROP_USHORT,
	KHPRMPROP_UINT,
	KHPRMPROP_ULONG,
	KHPRMPROP_FLOAT,
	KHPRMPROP_DOUBLE,
	KHPRMPROP_BASE,
	KHPRMPROP_STRING,
	KHPRMPROP_WSTRING,
};

// param flags
#define KHPRMF_GET							0x0001
#define KHPRMF_SET							0x0002
#define KHPRMF_NAME							0x0010
#define KHPRMF_DESC							0x0020
#define KHPRMF_FREE_DATA					0x0100
#define KHPRMF_RW							(KHPRMF_GET|KHPRMF_SET)
#define KHPRMF_STATICS						(KHPRMF_NAME|KHPRMF_DESC)

// operator table
struct khOpTable
{
	khOpFunc			_nop;

	khOpFunc			_pos;
	khOpFunc			_neg;
	khOpFunc			_sig;
	khOpFunc			_not;
	khOpFunc			_inc;
	khOpFunc			_dec;

	khOpFunc			_mul;
	khOpFunc			_div;
	khOpFunc			_mod;
	khOpFunc			_add;
	khOpFunc			_sub;
	khOpFunc			_shl;
	khOpFunc			_shr;
	khOpFunc			_blt;
	khOpFunc			_ble;
	khOpFunc			_beq;
	khOpFunc			_bne;
	khOpFunc			_and;
	khOpFunc			_xor;
	khOpFunc			_or;

	khOpFunc			_stv;
	khOpFunc			_ldv;

	khOpNewFunc			_new;
	khOpTosFunc			_tos;

	khOpFunc			_mnm;
};

// 
union khOpBind
{
	struct khOpTable		tbl;
	khOpFunc				ops[KHOP_MAX_VALUE];
};

// parameter desc
struct khParamDesc
{
	enum khParamTypes	prm;
	kint				flags;

	kType				type;
	kuint				key;		// symbol

	kchar*				name;
	kchar*				desc;
};

// paremeter desc for property
struct khParamPropDesc
{
	khParamDesc			base;
	kint				prop : 16;
	kint				offset : 16;
	khParamPropFunc		setter;
	khParamPropFunc		getter;
};

// parameter desc for function
struct khParamFuncDesc
{
	khParamDesc			base;
	khParamCallFunc		func;
	kpointer			data;
};

// reg for property
struct khParamPropReg
{
	const kchar*		name;
	kint				prop : 16;
	kint				offset : 16;
	const kchar*		desc;
	kint				flags;
};

// reg for function
struct khParamFuncReg
{
	const kchar*		name;
	khParamCallFunc		func;
	kpointer			data;
	const kchar*		desc;
	kint				flags;
};

// 
#define KHPARAM_PROP_REG(name,prop,offset,get,set,flags,desc)\
	{name, prop, offset, desc, flags | (get ? KHPRMF_GET : 0) | (set ? KHPRMF_SET : 0)}
#define KHPARAM_PROP_REG_SIMPLE(name,prop,offset,get,set)\
	{name, prop, offset, NULL, (get ? KHPRMF_GET : 0) | (set ? KHPRMF_SET : 0) | KHPRMF_STATICS}
#define KHPARAM_FUNC_REG(name,func,data,flags,desc)\
	{name, func, data, desc, flags}
#define KHPARAM_FUNC_REG_SIMPLE(name,func)\
	{name, func, NULL, NULL, KHPRMF_STATICS}

// arity
struct khArity
{
	kint				count;
	kVar*				vars;
};

// var
struct kVar
{
	kType				type;
	kany64				rv;
};

// stack
struct kScv
{
	kVar*				data;
	ksize_t				size;
	ksize_t				base;
	ksize_t				top;

	kint				arity;
	kpointer			aud;
};

// type info
struct kTypeInfo
{
	ksize_t				refs;
	ksize_t				accs;

	const kchar*		name;
	kchar*				desc;
	kuint				sym;

	kint				size;
	kint				roam;
	kint				flag;

	kint				opov;
	kint				id;
	kint				scnt;
	kint				ccnt;
	kcham				isval : 8;
	kcham				isref : 8;

	//
	kTypeFunc			type_init;
	kTypeFunc			type_fini;

	khCnstFunc			func_cnst;
	khDispFunc			func_disp;

	khEqFunc			func_eq;
	khHashFunc			func_hash;
	khKeyFunc			func_key;

	//
	union khOpBind		optbl;

	//
	kTypeInfo*			parent;
	kType*				children;

	kType				supers[1];
};

// type declaration 
typedef struct kTypeDecl
{
	kint				size;
	kint				flags;

	kTypeFunc			type_init;
	kTypeFunc			type_fini;

	khCnstFunc			func_cnst;
	khDispFunc			func_disp;
} kTypeDecl;


//////////////////////////////////////////////////////////////////////////
// type system

// type management
KAPI kType k_tmnt_get_type(const kchar* name);
KAPI kType k_tmnt_find_type(kuint sym);
KAPI kTypeInfo* k_tmnt_look_type(kType type);
KAPI kvoid k_tmnt_debug_print(kcham bytree);
KAPI kType k_tmnt_reg(const kchar* name, const kTypeDecl* decl, kType parent);
KAPI kType k_tmnt_reg_red(kint id, const kchar* name, const kTypeDecl* decl, kType parent);
KAPI kType k_tmnt_entry(const char* name, kType parent, kint size, kint flags, kTypeFunc t_init, kTypeFunc t_fini, khCnstFunc f_cnst, khDispFunc f_disp);
KAPI kBase* k_tmnt_cast_linear(kType type, kBase* ptr);
KAPI kBase* k_tmnt_cast_assert(kType type, kBase* ptr);

// type stub
KAPI kTypeInfo* k_type_get_info(kType type);
KAPI const char* k_type_get_name(kType type);
KAPI const char* k_type_get_desc(kType type);
KAPI kuint k_type_get_sym(kType type);
KAPI kint k_type_get_id(kType type);
KAPI kcham k_type_is_value(kType type);
KAPI kcham k_type_is_ref(kType type);
KAPI kint k_type_get_size(kType type);
KAPI kint k_type_get_roam(kType type);
KAPI kint k_type_get_flags(kType type, kint mask);
KAPI kint k_type_get_supers(kType type);
KAPI kint k_type_get_children(kType type);
KAPI kType k_type_get_child_nth(kType type, kint nth);
KAPI kType k_type_get_parent(kType type);
KAPI khOpFunc k_type_get_op(kType type, kint op);
KAPI kcham k_type_find_op(kType type, kuint op, khParamDesc** param, khOpFunc* opf);
KAPI khParamDesc* k_type_get_param(kType type, const char* name);
KAPI khParamDesc* k_type_find_param(kType type, kuint symbol);
KAPI void k_type_set_desc(kType type, const char* desc);
KAPI void k_type_set_roam(kType type, kuint roam);
KAPI void k_type_set_func_key(kType type, khKeyFunc func);
KAPI void k_type_set_func_hash(kType type, khHashFunc func);
KAPI void k_type_set_func_eq(kType type, khEqFunc func);
KAPI void k_type_set_func_type_fini(kType type, kTypeFunc func);
KAPI void k_type_set_func_base_cnst(kType type, khCnstFunc func);
KAPI void k_type_set_func_base_disp(kType type, khDispFunc func);
KAPI kcham k_type_set_ops(kType type, kint op, khOpFunc opf);
KAPI kcham k_type_set_optable(kType type, const struct khOpTable* opt);
KAPI kcham k_type_bind_param(kType type, kint id, khParamDesc* param);
KAPI kint k_type_bind_props(kType type, kint baseid, kint count, const struct khParamPropReg* regs);
KAPI kint k_type_bind_funcs(kType type, kint baseid, kint count, const struct khParamFuncReg* regs);

// operator
KAPI const char* kh_op_to_str(kint op);
KAPI kuint kh_op_to_sym(kint op);
KAPI kint kh_op_to_mask(kint op);

KAPI const char* kh_op_supp_op_tos(kVar* var, char* buf, kint size, kint* outlen);
KAPI kint kh_op_supp_stv(kType type, kVar* data, kVar* key, kVar* value);
KAPI kint kh_op_supp_ldv(kType type, kVar* data, kVar* key, kVar* value);
KAPI kint kh_op_supp_op_beq(kVar* ops);
KAPI kint kh_op_supp_op_bne(kVar* ops);
KAPI kint kh_op_supp_op_sig(kVar* ops);
KAPI kint kh_op_supp_op_stv(kVar* ops);
KAPI kint kh_op_supp_op_ldv(kVar* ops);
KAPI kint kh_op_supp_op_new(kVar* ret, kint arity, kVar* args);

// parameter shed
KAPI khParamShed* kh_prmshed_new(void);
KAPI kvoid kh_prmshed_delete(khParamShed* self);
KAPI kcham kh_prmshed_set(khParamShed* self, kType type, khParamDesc* desc);
KAPI kcham kh_prmshed_remove(khParamShed* self, khParamDesc* desc);
KAPI khParamDesc* kh_prmshed_get(khParamShed* self, kType type, const char* name, kcham recursive);
KAPI khParamDesc* kh_prmshed_try(khParamShed* self, kType type, kuint sym, kcham recursive);
KAPI khParamDesc* kh_prmshed_find(khParamShed* self, kType type, kuint sym, kcham recursive);

// param
KAPI khParamDesc* kh_param_alloc(ksize_t size, kint paramtype, const char* name, const char* desc, kint flags);
KAPI khParamDesc* kh_param_alloc_prop(const char* name, const char* desc, kint prop, kint offset, kint flags);
KAPI khParamDesc* kh_param_alloc_func(const char* name, const char* desc, khParamCallFunc func, kpointer data, kint flags);
KAPI kvoid kh_param_free(khParamDesc* self);

// var
KAPI kvoid k_var_check(kVar* p);
KAPI kvoid k_var_zero(kVar* p);
KAPI kvoid k_var_load(kVar* p);
KAPI kvoid k_var_unload(kVar* p);
KAPI const char* k_var_tos(const kVar* p, char* buf, kint size, kint* outlen);
KAPI kvoid k_var_agn(kVar* p, const kVar* o);
KAPI kvoid k_var_agn_base(kVar* p, kBase* o);
KAPI kvoid k_var_agn_type(kVar* p, kType type, kBase* ptr);
KAPI kvoid k_var_set(kVar* p, const kVar* o);
KAPI kvoid k_var_set_type(kVar* p, kType type, kBase* ptr);
KAPI kvoid k_var_set_null(kVar* p);
KAPI kvoid k_var_set_param(kVar* p, const khParamDesc* o);
KAPI kvoid k_var_set_ptr(kVar* p, kpointer o);
KAPI kvoid k_var_set_bool(kVar* p, kbool o);
KAPI kvoid k_var_set_int(kVar* p, kint o);
KAPI kvoid k_var_set_long(kVar* p, klong o);
KAPI kvoid k_var_set_float(kVar* p, float o);
KAPI kvoid k_var_set_double(kVar* p, double o);
KAPI kvoid k_var_set_base(kVar* p, kBase* o);
KAPI kvoid k_var_set_str(kVar* p, const char* str, kint len);
KAPI kvoid k_var_set_wcs(kVar* p, const kwchar* str, kint len);
KAPI kvoid k_var_set_sym(kVar* p, kuint o);
KAPI kvoid k_var_set_sym_flex(kVar* p, const char* str);
KAPI kvoid k_var_set_sym_static(kVar* p, const char* str);
KAPI kcham k_var_try_sym(kVar* p, const char* str);
KAPI kcham k_var_is_null(const kVar* p);
KAPI kcham k_var_is_not_null(const kVar* p);
KAPI kcham k_var_is_param(const kVar* p);
KAPI kcham k_var_is_ptr(const kVar* p);
KAPI kcham k_var_is_bool(const kVar* p);
KAPI kcham k_var_is_int(const kVar* p);
KAPI kcham k_var_is_long(const kVar* p);
KAPI kcham k_var_is_float(const kVar* p);
KAPI kcham k_var_is_double(const kVar* p);
KAPI kcham k_var_is_sym(const kVar* p);
KAPI kcham k_var_is_str(const kVar* p);
KAPI kcham k_var_is_wcs(const kVar* p);
KAPI kcham k_var_is_tbl(const kVar* p);
KAPI kcham k_var_is_fn(const kVar* p);
KAPI kcham k_var_test_num(const kVar* p);
KAPI kcham k_var_test_str(const kVar* p);
KAPI kcham k_var_test_int(const kVar* p);
KAPI kcham k_var_test_real(const kVar* p);
KAPI kcham k_var_test_key(const kVar* p);
KAPI kcham k_var_test_call(const kVar* p);
KAPI kcham k_var_test_type_of(const kVar* p, kType type);
KAPI kcham k_var_is_value(const kVar* p);
KAPI kcham k_var_is_ref(const kVar* p);
KAPI kcham k_var_safe_type(const kVar* p, kType type, kBase** o);
KAPI kcham k_var_safe_param(const kVar* p, khParamDesc** o);
KAPI kcham k_var_safe_ptr(const kVar* p, kpointer* o);
KAPI kcham k_var_safe_bool(const kVar* p, kbool* o);
KAPI kcham k_var_safe_int(const kVar* p, kint* o);
KAPI kcham k_var_safe_long(const kVar* p, klong* o);
KAPI kcham k_var_safe_float(const kVar* p, float* o);
KAPI kcham k_var_safe_double(const kVar* p, double* o);
KAPI kcham k_var_safe_sym(const kVar* p, kuint* o);
KAPI kcham k_var_safe_sym_str(const kVar* p, const char** str, kint* len);
KAPI kcham k_var_safe_base(const kVar* p, kBase** o);
KAPI kcham k_var_safe_as_str(const kVar* p, kRedStr** o);
KAPI kcham k_var_conv_bool(const kVar* p, kbool* o);
KAPI kcham k_var_conv_int(const kVar* p, kint* o);
KAPI kcham k_var_conv_long(const kVar* p, klong* o);
KAPI kcham k_var_conv_float(const kVar* p, float* o);
KAPI kcham k_var_conv_double(const kVar* p, double* o);
KAPI kcham k_var_conv_str(const kVar* p, const char** str, kint* len);
KAPI kcham k_var_conv_wcs(const kVar* p, const kwchar** str, kint* len);
KAPI const khParamDesc* k_var_unsafe_param(const kVar* p);
KAPI kpointer k_var_unsafe_ptr(const kVar* p);
KAPI kbool k_var_unsafe_bool(const kVar* p);
KAPI kint k_var_unsafe_int(const kVar* p);
KAPI klong k_var_unsafe_long(const kVar* p);
KAPI float k_var_unsafe_float(const kVar* p);
KAPI double k_var_unsafe_double(const kVar* p);
KAPI kuint k_var_unsafe_sym(const kVar* p);
KAPI kuint k_var_unsafe_sym_str(const kVar* p, const char** str, kint* len);
KAPI kBase* k_var_unsafe_base(const kVar* p);
KAPI const char* k_var_unsafe_str(const kVar* p, kint* len);
KAPI const kwchar* k_var_unsafe_wcs(const kVar* p, kint* len);

// stack container
KAPI kvoid k_scv_move_top(kScv* p, kVar* v);
KAPI kVar* k_scv_at(const kScv* p, kint at);
KAPI kVar* k_scv_at_top(const kScv* p);
KAPI kVar* k_scv_at_base(const kScv* p);
KAPI kVar* k_scv_at_ctnr(const kScv* p);
KAPI kVar* k_scv_at_pub(const kScv* p);
KAPI kVar* k_scv_at_self(const kScv* p);
KAPI kVar* k_scv_at_fn(const kScv* p);
KAPI kVar* k_scv_arg(const kScv* p, kint nth);
KAPI kint k_scv_arity(const kScv* p);
KAPI kpointer k_scv_aud(const kScv* p);
KAPI kVar* k_scv_pop(kScv* p);
KAPI kvoid k_scv_pop_ret(kScv* p, kVar* ret);
KAPI kvoid k_scv_agn(kScv* p, const kVar* v);
KAPI kvoid k_scv_agn_base(kScv* p, kBase* v);
KAPI kvoid k_scv_agn_type(kScv* p, kType type, kBase* ptr);
KAPI kvoid k_scv_push(kScv* p, const kVar* v);
KAPI kvoid k_scv_push_safe(kScv* p, const kVar* v);
KAPI kvoid k_scv_push_self(kScv* p, const kVar* self_or_null);
KAPI kvoid k_scv_push_type(kScv* p, kType type, kBase* ptr);
KAPI kvoid k_scv_push_null(kScv* p);
KAPI kvoid k_scv_push_param(kScv* p, const khParamDesc* v);
KAPI kvoid k_scv_push_ptr(kScv* p, kpointer v);
KAPI kvoid k_scv_push_bool(kScv* p, kbool v);
KAPI kvoid k_scv_push_int(kScv* p, kint v);
KAPI kvoid k_scv_push_long(kScv* p, klong v);
KAPI kvoid k_scv_push_float(kScv* p, float v);
KAPI kvoid k_scv_push_double(kScv* p, double v);
KAPI kvoid k_scv_push_base(kScv* p, kBase* v);
KAPI kvoid k_scv_push_str(kScv* p, const char* str, kint len);
KAPI kvoid k_scv_push_wcs(kScv* p, const kwchar* str, kint len);
KAPI kvoid k_scv_push_sym(kScv* p, kuint v);
KAPI kvoid k_scv_push_sym_flex(kScv* p, const char* v);
KAPI kvoid k_scv_push_sym_static(kScv* p, const char* v);
KAPI kcham k_scv_push_try_sym(kScv* p, const char* v);
KAPI kcham k_scv_arg_type(const kScv* p, kint nth, kType type, kBase** v);
KAPI kcham k_scv_arg_param(const kScv* p, kint nth, khParamDesc** v);
KAPI kcham k_scv_arg_ptr(const kScv* p, kint nth, kpointer* v);
KAPI kcham k_scv_arg_bool(const kScv* p, kint nth, kbool* v);
KAPI kcham k_scv_arg_int(const kScv* p, kint nth, kint* v);
KAPI kcham k_scv_arg_long(const kScv* p, kint nth, klong* v);
KAPI kcham k_scv_arg_float(const kScv* p, kint nth, float* v);
KAPI kcham k_scv_arg_double(const kScv* p, kint nth, double* v);
KAPI kcham k_scv_arg_sym(const kScv* p, kint nth, kuint* v);
KAPI kcham k_scv_arg_sym_str(const kScv* p, kint nth, const char** str, kint* len);
KAPI kcham k_scv_arg_base(const kScv* p, kint nth, kBase** v);
KAPI kcham k_scv_arg_num(const kScv* p, kint nth, double* v);
KAPI kcham k_scv_arg_str(const kScv* p, kint nth, const char** str, kint* len);
KAPI kcham k_scv_arg_wcs(const kScv* p, kint nth, const kwchar** str, kint* len);
KAPI kcham k_scv_arg_type_bool(const kScv* p, kint nth, kbool* v);
KAPI kcham k_scv_arg_type_int(const kScv* p, kint nth, kint* v);
KAPI kcham k_scv_arg_type_long(const kScv* p, kint nth, klong* v);
KAPI kcham k_scv_arg_type_float(const kScv* p, kint nth, float* v);
KAPI kcham k_scv_arg_type_double(const kScv* p, kint nth, double* v);
KAPI kcham k_scv_self_type(const kScv* p, kType type, kBase** ptr);
KAPI kcham k_scv_self_param(const kScv* p, khParamDesc** v);
KAPI kcham k_scv_self_ptr(const kScv* p, kpointer* v);
KAPI kcham k_scv_self_bool(const kScv* p, kbool* v);
KAPI kcham k_scv_self_int(const kScv* p, kint* v);
KAPI kcham k_scv_self_long(const kScv* p, klong* v);
KAPI kcham k_scv_self_float(const kScv* p, float* v);
KAPI kcham k_scv_self_double(const kScv* p, double* v);
KAPI kcham k_scv_self_sym(const kScv* p, kuint* v);
KAPI kcham k_scv_self_sym_str(const kScv* p, const char** str, kint* len);
KAPI kcham k_scv_self_base(const kScv* p, kBase** v);
KAPI kcham k_scv_self_num(const kScv* p, double* v);
KAPI kcham k_scv_self_str(const kScv* p, const char** str, kint* len);
KAPI kcham k_scv_self_wcs(const kScv* p, const kwchar** str, kint* len);
KAPI kcham k_scv_self_type_bool(const kScv* p, kbool* v);
KAPI kcham k_scv_self_type_int(const kScv* p, kint* v);
KAPI kcham k_scv_self_type_long(const kScv* p, klong* v);
KAPI kcham k_scv_self_type_float(const kScv* p, float* v);
KAPI kcham k_scv_self_type_double(const kScv* p, double* v);
KAPI const char* k_scv_self_tos(const kScv* p, char* buf, kint size, kint* len);
KAPI kBase* k_scv_unsafe_self_base(const kScv* p);
KAPI const char* k_scv_unsafe_self_str(const kScv* p, kint* len);
KAPI const kwchar* k_scv_unsafe_self_wcs(const kScv* p, kint* len);
KAPI kcham k_scv_arg_vascanf(kScv* p, const char* fmt, va_list va);
KAPI kcham k_scv_arg_scanf(kScv* p, const char* fmt, ...);


//////////////////////////////////////////////////////////////////////////
// base

// base
struct kBase
{
	kTypeInfo*			type_info;
	volatile kint		base_ref;
	kpointer			base_data;
};

// desc 
struct kDescBase
{
	kBase				base;
	kuintptr			hd;
};

// node
struct kNodeBase
{
	kDescBase			base;
	ksize_t				hash;
	kNodeBase*			sib;
	kNodeBase*			prev;
	kNodeBase*			next;
};

// node list
typedef struct kBaseList
{
	kNodeBase*			frst;
	kNodeBase*			last;
	ksize_t				count;
} kBaseList;

// node mukum
typedef struct kBaseMukum
{
	ksize_t				revision;
	ksize_t				bucket;
	ksize_t				count;
	kNodeBase**			nodes;
	kTypeInfo*			typeinfo;
} kBaseMukum;

// crbs
KAPI kBase* k_crbs_new(kType type);
KAPI kBase* k_crbs_check(kType type, kBase* self);

// base
KAPI kType k_base_type(void);
KAPI kBase* k_base_load(kBase* ptr);
KAPI kBase* k_base_unload(kBase* ptr);
KAPI kint k_base_ref_load(kBase* ptr);
KAPI kint k_base_ref_unload(kBase* ptr);
KAPI void k_base_pure_load(kBase* ptr);
KAPI void k_base_pure_unload(kBase* ptr);
KAPI void k_base_force_unload(kBase* ptr);
KAPI void k_base_force_revive(kBase* ptr);
KAPI int k_base_get_ref(kBase* ptr);
KAPI kType k_base_get_type(kBase* ptr);
KAPI kpointer k_base_get_userdata(kBase* ptr);
KAPI kpointer k_base_set_userdata(kBase* ptr, kpointer data);

KAPI kType k_descbase_type(void);
KAPI kuintptr k_descbase_get_desc(kDescBase* ptr);
KAPI kuintptr k_descbase_set_desc(kDescBase* ptr, kuintptr hd);

KAPI kType k_nodebase_type(void);
KAPI ksize_t k_nodebase_get_hash_code(kNodeBase* ptr);

// node list
#define k_baselist_count(p)		((p)->count)
#define k_baselist_first(p)		((p)->frst)
#define k_baselist_last(p)		((p)->last)
#define k_baselist_is_have(p)	((p)->count>0)
#define k_baselist_is_empty(p)	((p)->count==0)
KAPI void k_baselist_init(kBaseList* p);
KAPI void k_baselist_disp(kBaseList* p);
KAPI void k_baselist_clear(kBaseList* p);
KAPI void k_baselist_clear_chain(kBaseList* p);
KAPI void k_baselist_clear_force(kBaseList* p);
KAPI void k_baselist_append(kBaseList* p, kNodeBase* item);
KAPI void k_baselist_prepend(kBaseList* p, kNodeBase* item);
KAPI kNodeBase* k_baselist_remove(kBaseList* p, kNodeBase* item);
KAPI kNodeBase* k_baselist_remove_first(kBaseList* p);
KAPI kNodeBase* k_baselist_remove_last(kBaseList* p);
KAPI kcham k_baselist_contains(kBaseList* p, kNodeBase* item);
KAPI void k_baselist_foreach(kBaseList* p, void(*func2)(kpointer, kNodeBase*), kpointer userdata);
KAPI void k_baselist_loopeach(kBaseList* p, void(*func1)(kNodeBase*));

// node mukum
#define k_basemukum_count(p)	((p)->count)
#define k_basemukum_is_have(p)	((p)->count>0)
#define k_basemukum_is_empty(p)	((p)->count==0)
KAPI kcham k_basemukum_init(kBaseMukum* p, kType type);
KAPI void k_basemukum_disp(kBaseMukum* p);
KAPI void k_basemukum_clear(kBaseMukum* p);
KAPI void k_basemukum_clear_chain(kBaseMukum* p);
KAPI void k_basemukum_clear_force(kBaseMukum* p);
KAPI kcham k_basemukum_add(kBaseMukum* p, kNodeBase* base);
KAPI kNodeBase* k_basemukum_get(kBaseMukum* p, kconstpointer key);
KAPI kNodeBase* k_basemukum_remove(kBaseMukum* p, kconstpointer key);
KAPI kNodeBase* k_basemukum_remove_base(kBaseMukum* p, kNodeBase* base);
KAPI void k_basemukum_foreach(kBaseMukum* p, void(*func2)(kpointer, kNodeBase*), kpointer userdata);
KAPI void k_basemukum_loopeach(kBaseMukum* p, void(*func1)(kNodeBase*));


//////////////////////////////////////////////////////////////////////////
// red object
struct khTblNode;
struct khTblAnyCb;
struct khFnCode;
struct khObjCtn;

// string
struct kRedStr
{
	kBase				base;

	kcham				stt;

	kuint				sym;
	kint				len;
	kchar*				data;
};

// wide string
struct kRedWcs
{
	kBase				base;

	kcham				stt;

	kint				len;
	kwchar*				data;
};

// fn
struct kRedFn
{
	kBase				base;

	const char*			name;
	kDateTime			bdt;

	khParamCallFunc		func;
	struct khFnCode*	code;

	struct khObjCtn*	objs;
	
	kRedFn*				parent;
};

// table
struct kRedTbl
{
	kBase				base;

	kMutex*				lock;

	ksize_t				bucket;
	ksize_t				capa;
	ksize_t				count;

	struct khTblNode**	nodes;
	struct khTblNode**	anode;

	struct khTblAnyCb*	anys;

	kRedTbl*			parent;
};

// fn info
struct kRedFnInfo
{
	kint				size;
	kint				stack;
	kint				arity;
	kint				local;
	kint				var;
	kint				sym;
};

//
KAPI kType k_redstr_type(void);
KAPI kcham k_redstr_set_str(kRedStr* self, const char* str, kint len);
KAPI kcham k_redstr_set_sym(kRedStr* self, kuint sym);
KAPI const char* k_redstr_get_data(kRedStr* self);
KAPI kint k_redstr_get_len(kRedStr* self);
KAPI kuint k_redstr_get_sym(kRedStr* self);
KAPI kuint k_redstr_try_sym(kRedStr* self);
KAPI kuint k_redstr_build_sym(kRedStr* self, kcham istry);
KAPI kcham k_redstr_build_data(kRedStr* self);
KAPI kRedStr* k_redstr_get_static(const char* str);
KAPI void k_redstr_set_cache_size(kint count);
KAPI kint k_redstr_get_cache_size(void);
KAPI kint k_redstr_get_cache_count(void);
KAPI kRedStr* k_redstr_new(const char* init, kint len);
KAPI kRedStr* k_redstr_new_sym(kuint sym);
KAPI kRedStr* k_redstr_new_static(const char* init, kint len);
KAPI kRedStr* k_redstr_new_copy(kRedStr* self);

KAPI kType k_redwcs_type(void);
KAPI kcham k_redwcs_set_str(kRedWcs* self, const kwchar* str, kint len);
KAPI const kwchar* k_redwcs_get_data(kRedWcs* self);
KAPI kint k_redwcs_get_len(kRedWcs* self);
KAPI kRedWcs* k_redwcs_get_static(const kwchar* str);
KAPI void k_redwcs_set_cache_size(kint count);
KAPI kint k_redwcs_get_cache_size(void);
KAPI kint k_redwcs_get_cache_count(void);
KAPI kRedWcs* k_redwcs_new(const kwchar* init, kint len);
KAPI kRedWcs* k_redwcs_new_static(const kwchar* init, kint len);
KAPI kRedWcs* k_redwcs_new_copy(kRedWcs* ptr);

KAPI kType k_redtbl_type(void);
KAPI void k_redtbl_enter_lock(kRedTbl* self);
KAPI void k_redtbl_leave_lock(kRedTbl* self);
KAPI kcham k_redtbl_try(kRedTbl* self, const kVar* key, kVar* value);
KAPI kcham k_redtbl_get(kRedTbl* self, const kVar* key, kVar* value);
KAPI void k_redtbl_set(kRedTbl* self, const kVar* key, const kVar* value);
KAPI kcham k_redtbl_recursive_try(kRedTbl* self, const kVar* key, kVar* value);
KAPI kcham k_redtbl_recursive_get(kRedTbl* self, const kVar* key, kVar* value);
KAPI kcham k_redtbl_recursive_set(kRedTbl* self, const kVar* key, const kVar* value);
KAPI kcham k_redtbl_unsafe_get(kRedTbl* self, const kVar* key, kVar* value, ksize_t hash);
KAPI kcham k_redtbl_unsafe_set(kRedTbl* self, const kVar* key, const kVar* value, ksize_t hash);
KAPI void k_redtbl_unsafe_append(kRedTbl* self, const kVar* key, const kVar* value, ksize_t hash);
KAPI kcham k_redtbl_remove(kRedTbl* self, const kVar* key);
KAPI void k_redtbl_clear(kRedTbl* self);
KAPI void k_redtbl_add_tbl(kRedTbl* self, kRedTbl* from);
KAPI kcham k_redtbl_get_nth(kRedTbl* self, kint index, kVar* key, kVar* value);
KAPI kint k_redtbl_get_bucket(kRedTbl* self);
KAPI kint k_redtbl_get_count(kRedTbl* self);
KAPI void k_redtbl_set_parent(kRedTbl* self, kRedTbl* parent);
KAPI kcham k_redtbl_find(kRedTbl* self, const char* find, kVar* value);
KAPI void k_redtbl_bind_anys(kRedTbl* self, kpointer data, kfunc_1 disposer);
KAPI kcham k_redtbl_unbind_anys(kRedTbl* self, kpointer data, kcham needcall);
KAPI kcham k_redtbl_bind_param(kRedTbl* self, khParamDesc* param, kcham store);
KAPI kcham k_redtbl_bind_func(kRedTbl* self, kRedFn* rfn);
KAPI void k_redtbl_unsafe_bind_param(kRedTbl* self, khParamDesc* param, kcham store);
KAPI void k_redtbl_unsafe_bind_func(kRedTbl* self, kRedFn* rfn);
KAPI ksize_t k_redtbl_key_hash(const kVar* key);
KAPI kcham k_redtbl_key_eq(const kVar* k1, const kVar* k2);
KAPI void k_redtbl_set_cache_size(kint count);
KAPI kint k_redtbl_get_cache_size(void);
KAPI kint k_redtbl_get_cache_count(void);
KAPI void k_redtbl_debug_print(kRedTbl* self);
KAPI kRedTbl* k_redtbl_new(void);
KAPI kRedTbl* k_redtbl_new_copy(kRedTbl* from);

KAPI kType k_redfn_type(void);
KAPI const char* k_redfn_get_name(kRedFn* self);
KAPI const char* k_redfn_get_filename(kRedFn* self);
KAPI kint k_redfn_get_obj_count(kRedFn* self);
KAPI kBase* k_redfn_get_obj_nth(kRedFn* self, kint nth);
KAPI khParamCallFunc k_redfn_get_native_call(kRedFn* self);
KAPI kRedFn* k_redfn_get_parent(kRedFn* self);
KAPI kcham k_redfn_get_info(kRedFn* self, struct kRedFnInfo* info);
KAPI kuint* k_redfn_get_data(kRedFn* self);
KAPI kushort* k_redfn_get_line(kRedFn* self);
KAPI kuint k_redfn_get_sym_nth(kRedFn* self, kint nth);
KAPI kcham k_redfn_debug_file(kRedFn* self, kFile* file);
KAPI kcham k_redfn_debug_output(kRedFn* self, const char* filename);
KAPI void k_redfn_set_cache_size(kint count);
KAPI kint k_redfn_get_cache_size(void);
KAPI kint k_redfn_get_cache_count(void);
KAPI kRedFn* k_redfn_new(void);


//////////////////////////////////////////////////////////////////////////
// runtime

// run result
enum kRR
{
	KRR_OK = 0, // RUN
	KRR_END = 1, // EXIT
	KRR_WAIT = 2,
	KRR_BLOCK = 3,
	KRR_CALL = 4,
	KRR_ERROR = -1
};

// stack info
enum khRS
{
	KHRS_0 = 0, // BASE
	KHRS_SELF = -2,
	KHRS_FN = -1,
};

#define KHSF_NOWARN_MEM						K_BIT(0)
#define KHSF_NOCHECK_CALLARG				K_BIT(2)
#define KHSF_BREAK_EXCEPTION				K_BIT(15)
#define KHSF_TRACE_EXCEPTION				K_BIT(16)
#define KHSF_DEBUGGER						K_BIT(31)

// khsm
struct kHsm
{
	kBase				base;

	kint				flags;

	kint				parses;
	kint				compiles;
};

// khsp
struct kRnh
{
	kBase				base;

	kint				lerr;

	kHsm*				hsm;
	kRedFn*				cfn;
	kRedTbl*			pub;
};

//
KAPI kType k_hsm_type(void);
KAPI kRedTbl* k_hsm_get_super(kHsm* ptr);
KAPI kint k_hsm_get_flags(kHsm* ptr, kint mask);
KAPI kint k_hsm_get_stack_count(kHsm* ptr);
KAPI ksize_t k_hsm_get_stack_size(kHsm* ptr);
KAPI kint k_hsm_set_flags(kHsm* ptr, kint value);
KAPI kint k_hsm_set_stack_count(kHsm* ptr, kint count);
KAPI ksize_t k_hsm_set_stack_size(kHsm* ptr, ksize_t size);
KAPI kcham k_hsm_find_var(kHsm* ptr, const char* find, kVar* value);
KAPI kcham k_hsm_get_var(kHsm* ptr, const kVar* key, kVar* value);
KAPI void k_hsm_set_var(kHsm* ptr, const kVar* key, const kVar* value);
KAPI kint k_hsm_bind_libs(kHsm* ptr, const char* name, kint count, const struct khParamFuncReg* regs, kRedTbl** rettbl);
KAPI kcham k_hsm_bind_param(kHsm* ptr, const char* name, khParamDesc* prm);
KAPI kcham k_hsm_bind_func(kHsm* ptr, const char* name, kRedFn* rfn);
KAPI kRedFn* k_hsm_compile(kHsm* ptr, const char* name, const char* script, const char* filename_N, const char* output_N, kint* error_N);
KAPI kRedFn* k_hsm_compile_file(kHsm* ptr, const char* name, const char* filename, const char* output_N, kint* error_N);
KAPI kRnh* k_hsm_create_run(kHsm* ptr, kRedFn* cfn, kRedTbl* pub_N);
KAPI kRnh* k_hsm_create_run_compile(kHsm* ptr, const char* script, kRedTbl* pub_N, const char* filename_N, const char* output_N, kint* error_N);
KAPI kRnh* k_hsm_create_run_compile_file(kHsm* ptr, const char* filename, kRedTbl* pub_N, const char* output_N, kint* error_N);
KAPI kcham k_hsm_reg_lib(kHsm* ptr, kuint libid);
KAPI kHsm* k_hsm_new(kint flags);

KAPI kType k_rnh_type(void);
KAPI void k_rnh_clean(kRnh* ptr);
KAPI kcham k_rnh_run(kRnh* ptr, kRedFn* fn, kVar* retvar);
KAPI kcham k_rnh_run_main(kRnh* ptr, kVar* retvar);
KAPI kScv* k_rnh_prepare(kRnh* ptr, const char* lookup, const kVar* self_nullable);
KAPI kcham k_rnh_launch(kRnh* ptr, kint arity, kVar* retvar_nullable);


//////////////////////////////////////////////////////////////////////////
// library
#define KHLIB_SYSTEM						0x0001
#define KHLIB_MATH							0x0002

KAPI kuint k_hlib_sys(kHsm* hsm);
KAPI kuint k_hlib_math(kHsm* hsm);


//////////////////////////////////////////////////////////////////////////
// definition
#define KTYPE(_prefix)					K_CONTRI(_,_prefix,_type())

#define KTIMPL_BEGIN(_klass,_name,_prefix,_parent,_flag,_cnst,_disp)\
	static void K_CONTRI(_,_prefix,_init_type)(kType type);\
	static void K_CONTRI(_,_prefix,_fini_type)(kType type);\
	kType KTYPE(_prefix) {\
		static volatile kType type=0; if (k_once_try(&type)) {\
			kType p=k_tmnt_entry(_name,_parent,sizeof(_klass),_flag,K_CONTRI(_,_prefix,_init_type),K_CONTRI(_,_prefix,_fini_type),_cnst,_disp); {
#define KTIMPL_END()\
			} k_once_leave(&type,p);\
		} return type;\
	}

#define KTIMPL_EXTEND(_klass,_name,_prefix,_parent,_flag,_cnst,_disp,_code)\
	KTIMPL_BEGIN(_klass,_name,_prefix,_parent,_flag,_disp,_code)\K_STMT_BEGIN{_code;}K_STMT_END;\KTIMPL_END()

K_EXTERN_C_END

#endif	// __SBHS_H__
